﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using DevelopTool.Bll.ChatBlls;
using DevelopTool.Common;
using DevelopTool.Forms.ChatForms.MessageItemControls;
using DevelopTool.Model.ChatModels;
using DevelopTool.Model.Enums;
using Sunny.UI;

namespace DevelopTool.Forms.ChatForms
{
    /// <summary>
    /// 聊天控件
    /// </summary>
    public partial class ChatSessionControl : UIUserControl
    {
        /// <summary>
        /// 会话用户
        /// </summary>
        private ChatUser sessionChatUser;

        /// <summary>
        /// 会话用户
        /// </summary>
        public ChatUser SessionChatUser
        {
            get
            {
                return this.sessionChatUser;
            }
            set
            {
                this.sessionChatUser = value;
                SetSessionUserInfo();
            }
        }

        private ChatBll chatBll;

        public ChatSessionControl(ChatUser sessionChatUser)
        {
            InitializeComponent();

            this.sessionChatUser = sessionChatUser;
        }


        private void ChatSessionControl_Load(object sender, EventArgs e)
        {
            this.Disposed += ChatSessionControl_Disposed;
            ChatBll.ChatNewMessageEvent += ChatBll_ChatNewMessageEvent;
            ChatBll.ChatDeleteMessageEvent += ChatBll_StaticDeleteMessageEvent;
            chatBll = new ChatBll();

            #region 设置控件的Tips
            this.uiToolTip.SetToolTip(this.btnSend, this.btnSend.TipsText);
            this.uiToolTip.SetToolTip(this.btnSendFile, this.btnSendFile.TipsText);
            this.uiToolTip.SetToolTip(this.btnSendImage, this.btnSendImage.TipsText);
            this.uiToolTip.SetToolTip(this.btnSendScreenShot, this.btnSendScreenShot.TipsText);

            #endregion 设置控件的Tips


            #region 昵称

            //有备注时显示备注，没有备注则显示昵称
            this.pnlTitle.Text = string.IsNullOrEmpty(sessionChatUser.RemarkName) ? sessionChatUser.NikeName : sessionChatUser.RemarkName;

            //如果昵称和备注都没有，那么就只显示ip
            if (string.IsNullOrEmpty(this.pnlTitle.Text))
            {
                this.pnlTitle.Text = sessionChatUser.IP;
            }

            #endregion 昵称

            ThemHelper.SetSystemThem(this);

            this.backgroundWorker_LoadSessionMessage.RunWorkerAsync();

            this.pnlTitle.FillColor = Setting.Theme.BackColor;
            this.BackColor = Setting.Theme.BackColor;
            this.foreColor = Color.White;
        }



        private void SetSessionUserInfo()
        {
            this.btnSendFile.Enabled = sessionChatUser.IsLine;
        }


        #region 发送文本消息

        /// <summary>
        /// 发送文本消息按钮事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSend_Click(object sender, EventArgs e)
        {
            SendTextMessgae();
        }

        /// <summary>
        /// 文本输入框回车事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtMessageInput_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter && e.Modifiers == Keys.Shift)//忽略Shift+Enter按键
            {

            }
            else if (e.KeyCode == Keys.Enter)//按Enter键发送消息
            {
                // 阻止Enter键的默认行为（比如换行）  
                e.SuppressKeyPress = true;

                SendTextMessgae();
            }
        }


        /// <summary>
        /// 发送文本消息
        /// </summary>
        private void SendTextMessgae()
        {
            if (string.IsNullOrEmpty(this.txtMessageInput.Text)) return;

            if (!this.sessionChatUser.IsLine)
            {
                UIMessageTip.ShowWarning(this.btnSend, $"用户[{this.pnlTitle.Text}]不在线，暂无法发送消息", 1000, true, false);
                return;
            }

            this.btnSend.Enabled = false;

            ChatRecord chatRecord = new ChatRecord
            {
                ChatSessionType = ChatSessionType.User,
                ChatMessageType = ChatMessageType.Text,
                Text = this.txtMessageInput.Text,
                SendUser = this.chatBll.GetCurrentUserAllInfo(),
                ReceiverUser = this.sessionChatUser,
                Group = null
            };

            this.chatBll.SaveChatRecord(chatRecord);

            MessageItemPanel messageItemPanel = this.displayMessage(chatRecord);
            messageItemPanel.Send(record =>
            {
                if (record.SendState != ChatMessageSendState.Success)
                {
                    UIMessageTip.ShowWarning(this.btnSend, "发送消息失败", 1000, true, false);
                }
                messageItemPanel.ChatRecord = record;
            });

            this.txtMessageInput.Text = string.Empty;
            this.btnSend.Enabled = true;

        }

        #endregion 发送文本消息


        /// <summary>
        /// 发送文件按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSendFile_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog dialog = new OpenFileDialog { Title = "请选择需要发送的文件" })
            {
                dialog.Multiselect = true;//允许文件多选
                dialog.AutoUpgradeEnabled = true;
                dialog.CheckFileExists = true;
                dialog.CheckPathExists = true;
                dialog.DereferenceLinks = true;

                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    this.btnSendFile.Enabled = false;

                    SendBinary(dialog.FileNames);

                    this.btnSendFile.Enabled = true;
                }
            }
        }


        /// <summary>
        /// 发送图片按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSendImage_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog dialog = new OpenFileDialog { Title = "请选择需要发送的图片" })
            {
                dialog.Multiselect = true;//允许文件多选
                dialog.AutoUpgradeEnabled = true;
                dialog.CheckFileExists = true;
                dialog.CheckPathExists = true;
                dialog.DereferenceLinks = true;
                dialog.Filter = ImageHelper.GetImageFilter();

                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    this.btnSendImage.Enabled = false;

                    SendBinary(dialog.FileNames);

                    this.btnSendImage.Enabled = true;
                }
            }
        }


        /// <summary>
        /// 发送文件
        /// </summary>
        /// <param name="files"></param>
        private void SendBinary(string[] files)
        {
            if (files != null && files.Length > 0)
            {
                foreach (var file in files)
                {
                    FileInfo fileInfo = new FileInfo(file);

                    ChatFileMetaData chatFileMetaData = new ChatFileMetaData()
                    {
                        FileId = Guid.NewGuid().ToString("N"),
                        FileName = fileInfo.Name,
                        FileLocalPath = file,
                        Length = fileInfo.Length,
                    };

                    ChatRecord chatRecord = new ChatRecord
                    {
                        ChatSessionType = ChatSessionType.User,
                        ChatFileMetaData = chatFileMetaData,
                        SendUser = this.chatBll.GetCurrentUserAllInfo(),
                        ReceiverUser = this.sessionChatUser,
                        Group = null
                    };

                    //确定文件类型
                    if (ImageHelper.IsImage(file))
                    {
                        chatRecord.ChatMessageType = ChatMessageType.Image;//图片
                    }
                    else
                    {
                        chatRecord.ChatMessageType = ChatMessageType.File;//文件
                    }

                    this.chatBll.SaveChatRecord(chatRecord);

                    MessageItemPanel messageItemPanel = this.displayMessage(chatRecord);
                    messageItemPanel.Send(record =>
                    {
                        if (record.SendState != ChatMessageSendState.Success)
                        {
                            UIMessageTip.ShowWarning(this.btnSend, $"{record.ChatFileMetaData.FileName}发送失败", 1000, true, false);
                        }
                        messageItemPanel.ChatRecord = record;
                    });
                }
            }
        }


        #region  加载会话消息

        private void backgroundWorker_LoadSessionMessage_DoWork(object sender, DoWorkEventArgs e)
        {
            var recordList = this.chatBll.GetSessionUserRecordList(this.sessionChatUser.UserId);

            this.backgroundWorker_LoadSessionMessage.ReportProgress(1, recordList);
        }


        private void backgroundWorker_LoadSessionMessage_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.UserState is List<ChatRecord> recordList)
            {
                foreach (var record in recordList)
                {
                    displayMessage(record);
                }
            }
        }
        #endregion 加载会话消息


        #region 监控消息

        /// <summary>
        /// 接收到新消息事件
        /// </summary>
        /// <param name="sendChatUser"></param>
        /// <param name="chatRecord"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void ChatBll_ChatNewMessageEvent(ChatRecord chatRecord)
        {
            this.BeginInvoke(new Action(() =>
            {
                displayMessage(chatRecord);
            }));
        }

        /// <summary>
        /// 删除聊天消息事件
        /// </summary>
        /// <param name="chatRecord"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void ChatBll_StaticDeleteMessageEvent(ChatRecord chatRecord)
        {
            string controlName = chatRecord.Id + chatRecord.SendUser.UserId + chatRecord.ReceiverUser.UserId;

            MessageItemPanel messageItemPanel = this.pnlMessageList.Get<MessageItemPanel>(controlName);

            this.pnlMessageList.Controls.Remove(messageItemPanel);

            //foreach (Control control in this.pnlMessageList.Controls)
            //{
            //    if (controlName == control.Name)
            //    {
            //        this.pnlMessageList.Controls.Remove(control);
            //        break;
            //    }
            //}

        }

        /// <summary>
        /// 展示消息
        /// </summary>
        /// <param name="sendChatUser"></param>
        /// <param name="chatRecord"></param>
        private MessageItemPanel displayMessage(ChatRecord chatRecord)
        {

            string controlName = chatRecord.Id + chatRecord.SendUser.UserId + chatRecord.ReceiverUser.UserId;

            MessageItemPanel messageItemPanel = this.pnlMessageList.Get<MessageItemPanel>(controlName);
            if (messageItemPanel == null)
            {
                messageItemPanel = new MessageItemPanel(chatRecord);
                messageItemPanel.Name = controlName;
                messageItemPanel.TagString = chatRecord.Id.ToString();
                messageItemPanel.Width = pnlMessageList.DisplayRectangle.Width - pnlMessageList.ScrollBarWidth - pnlMessageList.ScrollBarHandleWidth;
                this.pnlMessageList.Add(messageItemPanel);

                this.pnlMessageList.ScrollControlIntoView(messageItemPanel);//定位滚动条到当前消息控件
            }
            else
            {
                messageItemPanel.ChatRecord = chatRecord;
            }

            return messageItemPanel;
        }


        #endregion 监控消息


        private void ChatSessionControl_Disposed(object sender, EventArgs e)
        {
            if (this.backgroundWorker_LoadSessionMessage.IsBusy && !this.backgroundWorker_LoadSessionMessage.CancellationPending)
            {
                this.backgroundWorker_LoadSessionMessage.CancelAsync();
            }

            ChatBll.ChatNewMessageEvent -= ChatBll_ChatNewMessageEvent;
        }


        /// <summary>
        /// 窗体大小改变事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void pnlMessageList_SizeChanged(object sender, EventArgs e)
        {
            var controls = this.pnlMessageList.AllControls;

            foreach (var control in controls)
            {
                if (control is MessageItemPanel messageItemPanel)
                {
                    messageItemPanel.Width = pnlMessageList.DisplayRectangle.Width - pnlMessageList.ScrollBarWidth - pnlMessageList.ScrollBarHandleWidth;
                    messageItemPanel.SizeChanged();
                }
            }
        }


    }
}
